//
//  QSRouter.swift
//  BeeBoxClient
//
//  Created by Song on 2019/4/29.
//  Copyright © 2019 Song. All rights reserved.
//

import QSExtensions
import RxSwift

// 复用控制器的通知
private let kReuseVcNot = "QSExtensions_ReuseVcNot"

/// 跳转类型
enum QSJumpType {
    case push
    case present
    case presentWithNav
}

class QSRouter {
    /// 界面跳转
    ///
    /// - Parameters:
    ///   - vc: 跳转后最终展示的控制器
    ///   - rootVc: vc所属的根控制器（适用TabBarController的情况）
    ///   - returnToVc: 返回的界面（会销毁中间界面，以适配手势返回）
    ///   - routerModel: 跳转时携带的参数
    ///   - jumpType: 跳转类型，默认push
    ///   - isAnimated: 跳转时是否需要动画，默认有动画
    ///   - isReuse: 是否复用已存在的控制器，默认不复用
    ///   - presentComplete: present跳转完成后回调
    class func qs_open(_ vc: AnyClass, rootVc: AnyClass? = nil, returnToVc: AnyClass? = nil, routerModel: QSBaseRouterModel? = nil, jumpType: QSJumpType = .push, isAnimated: Bool = true, isReuse: Bool = false, presentComplete: (()->Void)? = nil) {
        // 当前执行跳转的控制器
        guard let currentVc1 = qs_getCurrentVc() else { return }
        
        if isReuse {
            // 发送复用控制器通知
            let notificationName = Notification.Name(rawValue: kReuseVcNot)
            NotificationCenter.default.post(name: notificationName, object: currentVc1, userInfo: ["data": routerModel ?? ""])
        }
        
        // 跳转界面所需参数
        var parasModel = QSBaseRouterModel.init()
        if routerModel != nil {
            parasModel = routerModel!
        }
        parasModel.fromVc = returnToVc ?? currentVc1.classForCoder
        
        // 要跳转过去的根控制器
        if let cls = vc as? QSRoutable.Type {
            // 是否跳tabbar的子控制器
            if let rootV = rootVc {
                qs_openTabBarSubVc(rootV)
            }
            
            // 获取最新当前控制器
            if let currentVc = qs_getCurrentVc() {
                if currentVc.isKind(of: vc) {
                    return
                }
                
                if currentVc.navigationController != nil && jumpType == .push {
                    if currentVc.navigationController?.visibleViewController?.isKind(of: vc) ?? false {
                        return
                    }
                    
                    // 如果控制器存在且进行复用
                    if isReuse {
                        for reuseVc in (currentVc.navigationController?.children)! {
                            if reuseVc.classForCoder == cls {
                                currentVc.navigationController?.popToViewController(reuseVc, animated: isAnimated)
                                
                                return
                            }
                        }
                    }
                    
                    // 要跳转过去的控制器
                    if let toVc = cls.qs_initWithParmsModel?(parasModel) {
                        qs_pushVc(toVc, returnToVc: returnToVc, animated: isAnimated)
                    }
                } else {
                    // 要跳转过去的控制器
                    if let toVc = cls.qs_initWithParmsModel?(parasModel) {
                        toVc.hidesBottomBarWhenPushed = true
                        
                        if jumpType == .present {
                            currentVc.present(toVc, animated: isAnimated, completion: presentComplete)
                        } else if jumpType == .presentWithNav {
                            let navVc = UINavigationController.init(rootViewController: toVc)
                            currentVc.present(navVc, animated: isAnimated, completion: presentComplete)
                        }
                    }
                }
            }
        }
    }
    
    /// 监听复用控制器通知
    /// - Parameters:
    ///   - type: 通知发送的数据类型
    ///   - observer: 监听者
    ///   - usingBlock: 方法回调
    ///   - disposeBag: 销毁
    class func qs_observeReuseVcNot<T>(type:T.Type, observer: NSObject, usingBlock: @escaping ((T?) -> ()), disposeBag: DisposeBag) {
        NotificationCenter.default.rx
        .notification(Notification.Name(rawValue: kReuseVcNot))
        .takeUntil(observer.rx.deallocated) // 页面销毁自动移除通知监听
            .map { (not) -> T? in
                if let data = not.userInfo?["data"] as? T {
                    return data
                }
                
                return nil
        }.bind(onNext: usingBlock)
        .disposed(by: disposeBag)
    }
    
    /// 获取当前控制器
    class func qs_getCurrentVc() -> UIViewController? {
        guard let rootVc = UIApplication.shared.keyWindow?.rootViewController else { return nil }
        
        if let tabBarVc = qs_getTabBarVc() {
            if let navVc = tabBarVc.selectedViewController as? UINavigationController {
                return navVc.visibleViewController
            } else {
                return tabBarVc.selectedViewController
            }
        }
        
        if let rootNavVc = rootVc as? UINavigationController {
            return rootNavVc.visibleViewController
        }
        
        if let presentedVc = rootVc.presentedViewController {
            return presentedVc
        }
        
        return rootVc
    }
    
    /// 获取TabBar控制器
    private class func qs_getTabBarVc() -> UITabBarController? {
        guard let rootVc = UIApplication.shared.keyWindow?.rootViewController else { return nil }
        
        if let tabBarVc = rootVc as? UITabBarController {
            return tabBarVc
        }
        
        return nil
    }
    
    /// 跳转到TabBarController中的某个tab
    /// - Parameter vc: tab控制器
    private class func qs_openTabBarSubVc(_ vc: AnyClass) {
        // 获取tabBarViewController
        if let tabBarVc = qs_getTabBarVc() {
            if let tabBarVcs = tabBarVc.viewControllers {
                for i in 0 ..< tabBarVcs.count {
                    let tabSubVc = tabBarVcs[i]
                    
                    if let navVc = tabSubVc as? UINavigationController {
                        if let subVc = navVc.children.first {
                            if subVc.classForCoder == vc {
                                if let currentVC = qs_getCurrentVc() {
                                    currentVC.navigationController?.popToRootViewController(animated: false)
                                }
                                tabBarVc.selectedIndex = i
                            }
                        }
                    } else {
                        if tabSubVc.classForCoder == vc {
                            tabBarVc.selectedIndex = i
                        }
                    }
                }
            }
        }
    }
    
    /// push控制器
    private class func qs_pushVc(_ vc: UIViewController, returnToVc: AnyClass? = nil, animated: Bool) {
        vc.hidesBottomBarWhenPushed = true
        if let currentVc = self.qs_getCurrentVc() {
            currentVc.navigationController?.pushViewController(vc, animated: animated)
            
            if let returnTo = returnToVc {
                // 界面完全显示时，删除中间控制器
                let disposable = vc.rx.qs_viewDidAppear
                    .bind { _ in
                        var targetVc: UIViewController? = nil
                        var tmpVcArr = vc.navigationController?.viewControllers ?? []
                        
                        // 获取目标控制器索引
                        for i in 0 ..< tmpVcArr.count {
                            let subVc = tmpVcArr[i]
                            if subVc.isKind(of: returnTo) {
                                targetVc = subVc
                                break
                            }
                        }
                        
                        // 目标控制器
                        if let target = targetVc {
                            if let index = tmpVcArr.firstIndex(of: target) {
                                // 移除目标控制器与当前控制器之间的所有控制器
                                let range = NSRange.init(location: index + 1, length: tmpVcArr.count - 1 - (index + 1))
                                
                                if let rng = Range.init(range) {
                                    tmpVcArr.removeSubrange(rng)
                                    
                                    // 重新赋值给导航控制器
                                    vc.navigationController?.viewControllers = tmpVcArr
                                }
                            }
                        }
                }
                
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0) {
                    // 销毁订阅
                    disposable.dispose()
                }
            }
        }
    }
}
